package com.xbts.screen.monitor.domain.schedule;

import com.xbts.screen.monitor.domain.token.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

/**
 * 定时任务类：更新token
 * TODO: 当前版本暂未支持自动刷新token
 */
public class UpdateTokenSchedule {
    public static final Logger logger = LoggerFactory.getLogger(UpdateTokenSchedule.class);

    //token存储方式：这里采用本地缓存，如需修改，可替换为Redis或MySQL存储
    public static final TokenStore tokenStore = new LocalTokenStore();
    private static final Object lock = new Object();
    private static UpdateTokenSchedule instance;
    public static final Map<String, OauthConfigBaseInfo> httpConfigMap = new ConcurrentHashMap<String, OauthConfigBaseInfo>();
    //2分钟刷新一次过期token
    private static final Long expireTime = 120 * 1000L;
    //线程刷新token和保活
    private static final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
    //初始延迟
    private static final Long INITIAL_DELAY = 0L;
    //执行任务延迟
    private static final Long FRESH_TOKEN_INTERVAL = 2L;

    private UpdateTokenSchedule(){
        //定时刷新token
//        executorService.scheduleWithFixedDelay(new Thread()() -> {
//            logger.info("UpdateTokenSchedule,UpdateTokenSchedule,Start refreshing token...");
//            updateToken();
//        }, INITIAL_DELAY, FRESH_TOKEN_INTERVAL, TimeUnit.SECONDS);
    }
//
//    public static UpdateTokenSchedule getInstance(){
//        if(instance == null){
//            synchronized (lock){
//                if(instance == null){
//                    instance = new UpdateTokenSchedule();
//                }
//            }
//        }
//        return instance;
//    }

    public void updateToken(){
        Object o = tokenStore.getToken();
        if(o != null){
//            dealToken(o);
        }else {
            logger.info("Token story is empty, update token task return.");
        }
    }

    public void dealToken(Object o){
        if(tokenStore instanceof MysqlTokenStore){
            logger.info("Update token from mysql.");
            MysqlTokenStore mysqlTokenStore = (MysqlTokenStore) tokenStore;
            Map<String, Token> tokens = (Map<String, Token>)o;
            if(CollectionUtils.isEmpty(tokens)){
                logger.info("Mysql token story is empty, update token task return.");
                return;
            }
//            dealExpiredToken(mysqlTokenStore, tokens);
        }

        if(tokenStore instanceof RedisTokenStore){
            logger.info("Update token from redis.");
            RedisTokenStore redisTokenStore = (RedisTokenStore) tokenStore;
            Map<String, String> tokens = (Map<String, String>)o;
            if(CollectionUtils.isEmpty(tokens)){
                logger.info("Redis token story is empty, update token task return.");
                return;
            }
//            dealExpiredToken(redisTokenStore, tokens);
        }

        if(tokenStore instanceof LocalTokenStore){
            logger.info("Update token from local story.");
            LocalTokenStore localTokenStore = (LocalTokenStore) tokenStore;
            Map<String, Token> tokenMap = (Map<String, Token>)o;
            if(CollectionUtils.isEmpty(tokenMap)) {
                logger.info("Local map token story is empty, update token task return.");
                return;
            }
//            dealExpiredToken(localTokenStore, tokenMap);
        }
    }

//    public void dealExpiredToken(MysqlTokenStore mysqlTokenStore, Map<String, Token> tokenMap){
//        for (Map.Entry entry : tokenMap.entrySet()){
//            String key = (String) entry.getKey();
//            Token token = (Token) entry.getValue();
//            Long ttl = token.getTtl();
//
//            //token剩余过期时间小于等于2分钟时，更新token
//            if(ttl - System.currentTimeMillis() <= expireTime){
//                logger.info("UpdateTokenSchedule,dealExpiredToken, key:{}", key);
//                token = refreshToken(key, token.getRefresh_token());
//                if(token == null)return;
//                //生成用于缓存的key
//                OauthConfigBaseInfo oauthConfigBaseInfo = httpConfigMap.get(key);
//                String tokenKey = getKey(oauthConfigBaseInfo);
//                if(StringUtils.isEmpty(tokenKey))return;
//                //将token进行缓存
//                mysqlTokenStore.updateToken(tokenKey, token);
//            }
//        }
//
//    }

//    public void dealExpiredToken(LocalTokenStore localTokenStore, Map<String, Token> tokenMap){
//        for (Map.Entry entry : tokenMap.entrySet()){
//            String key = (String) entry.getKey();
//            Token token = (Token) entry.getValue();
//            Long ttl = token.getTtl();
//
//            //token剩余过期时间小于等于2分钟时，更新token
//            if(ttl - System.currentTimeMillis() <= expireTime){
//                logger.info("UpdateTokenSchedule,dealExpiredToken, key:{}", key);
//                token = refreshToken(key, token.getRefresh_token());
//                if(token == null)return;
//                //生成用于缓存的key
//                OauthConfigBaseInfo oauthConfigBaseInfo = httpConfigMap.get(key);
//                String tokenKey = getKey(oauthConfigBaseInfo);
//                if(StringUtils.isEmpty(tokenKey))return;
//                //将token进行缓存
//                localTokenStore.tokenMap.put(tokenKey, token);
//            }
//        }
//    }

//    public void dealExpiredToken(RedisTokenStore redisTokenStore, Map<String, String> tokens){
//        for (Map.Entry entry : tokens.entrySet()){
//            String key = (String) entry.getKey();
//            String value = (String) entry.getValue();
//            Token token = JSON.parseObject(value, Token.class);
//            Long ttl = token.getTtl();
//
//            //token剩余过期时间小于等于2分钟时，更新token
//            if(ttl - System.currentTimeMillis() <= expireTime){
//                logger.info("UpdateTokenSchedule,dealExpiredToken, key:{}", key);
//                token = refreshToken(key, token.getRefresh_token());
//                if(token == null)return;
//                //生成用于缓存的key
//                OauthConfigBaseInfo oauthConfigBaseInfo = httpConfigMap.get(key);
//                String tokenKey = getKey(oauthConfigBaseInfo);
//                if(StringUtils.isEmpty(tokenKey))return;
//                //将token进行缓存
//                redisTokenStore.updateToken(tokenKey, token);
//            }
//        }
//    }

    public Token refreshToken(String key, String refreshToken){
        Token newToken = null;
//        OauthConfigBaseInfo oauthConfigBaseInfo = httpConfigMap.get(key);
//
//        //目前只支持密码模式
//        if(oauthConfigBaseInfo.getGrantType() == GrantType.password){
//            OauthRefreshTokenRequest oauthRefreshTokenRequest = new OauthRefreshTokenRequest(oauthConfigBaseInfo, refreshToken);
//            OauthRefreshTokenResponse oauthRefreshTokenResponse = oauthRefreshTokenRequest.doAction();
//            if(oauthRefreshTokenResponse.isSuccess()){
//                OauthRefreshTokenResponse.IccReFreshToken  iccReFreshToken = oauthRefreshTokenResponse.getData();
//                newToken = new Token();
//                BeanUtils.copyProperties(iccReFreshToken, newToken);
//                //设置过期时间
//                newToken.setTtl(System.currentTimeMillis() + iccReFreshToken.getExpires_in() * 1000);
//                return newToken;
//            }else{
//                logger.error("UpdateTokenSchedule,refreshToken, error:{}", key);
//                return null;
//            }
//        }
//        //客户端模式，暂不作处理
//        else if(oauthConfigBaseInfo.getGrantType() == GrantType.client_credentials){
//
//        }
        return newToken;
    }

    public static String getKey(OauthConfigBaseInfo oauthConfigBaseInfo){
        if(oauthConfigBaseInfo.getGrantType() == GrantType.password){
            String host = oauthConfigBaseInfo.getHttpConfigInfo().getHost();
            String grantType = oauthConfigBaseInfo.getGrantType().name();
            String userName = null;
            OauthConfigUserPwdInfo oauthConfigUserPwdInfo = (OauthConfigUserPwdInfo)oauthConfigBaseInfo;
            userName = oauthConfigUserPwdInfo.getUsername();
            String key = host + "_" + grantType + "_" + userName;
            logger.info("UpdateTokenSchedule,getKey, key:{}", key);
            return key;
        }
        return null;
    }
}
